package cn.xinfei.xdecision.common.service.common.sso.impl;

import cn.xinfei.xdecision.common.model.BaseVO;
import cn.xinfei.xdecision.common.service.common.sso.SSOService;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOCheckTokenReqDto;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSORespBody;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOUserInfoReqDto;
import cn.xinfei.xdecision.common.service.common.sso.dto.SSOUserInfoRespDto;
import cn.xinfei.xdecision.common.utils.exception.ApiException;
import cn.xinfei.xdecision.common.utils.util.CollectionUtil;
import cn.xinfei.xdecision.common.utils.util.OKHttpClientManage;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.xinfei.xdecision.common.utils.exception.enums.ErrorCodeEnum.AUTH_SSO_SYSTEM_ERROR;

/**
 * Created by maying on 2023/03/10.
 **/
@Service
@Slf4j
public class SSOServiceImpl implements SSOService {
	@Value("${xdecision.sso.domain:default_value}")
	private String domain;
	@Value("${xdecision.sso.appName:default_value}")
	private String appName;
	@Value("${xdecision.sso.getUserInfoUri:default_value}")
	private String getUserInfoUri;
	@Value("${xdecision.sso.checkLoginToken:default_value}")
	private String checkLoginToken;

	@Override
	public SSORespBody checkToken(SSOCheckTokenReqDto ssoCheckTokenReqDto) {
		return postSSO(domain+checkLoginToken,JSONObject.toJSONString(ssoCheckTokenReqDto));
	}

	@Override
	public List<SSOUserInfoRespDto> getUserInfos(SSOUserInfoReqDto ssoUserInfoReqDto) {
		SSORespBody respBody = postSSO(domain+getUserInfoUri,JSONObject.toJSONString(ssoUserInfoReqDto));
		Object data = respBody.getData();
		return JSONObject.parseArray(JSONObject.toJSONString(data), SSOUserInfoRespDto.class);
	}

	@Override
	public SSOUserInfoRespDto getUserInfoById(long userId) {
		SSOUserInfoReqDto ssoUserInfoReqDto = new SSOUserInfoReqDto();
		ssoUserInfoReqDto.setId(Collections.singletonList(userId));
		List<SSOUserInfoRespDto> userInfoRespDtos = getUserInfos(ssoUserInfoReqDto);
		if(userInfoRespDtos != null && !userInfoRespDtos.isEmpty()){
			return userInfoRespDtos.get(0);
		}
		return null;
	}

	@Override
	public List<? extends BaseVO> fillUserInfoToVO(List<? extends BaseVO> vos) {
		Set<Long> userIds = new HashSet<>();
		for(BaseVO baseVO : vos){
			userIds.add(baseVO.getCreateUserId());
			userIds.add(baseVO.getUpdateUserId());
		}

		if(CollectionUtil.isNotNullOrEmpty(userIds)){
			SSOUserInfoReqDto ssoUserInfoReqDto = new SSOUserInfoReqDto();
			ssoUserInfoReqDto.setId(new ArrayList<>(userIds));
			List<SSOUserInfoRespDto> userInfoRespDtos = getUserInfos(ssoUserInfoReqDto);

			Map<Long,SSOUserInfoRespDto> userInfoRespDtoMap = userInfoRespDtos.stream().collect(Collectors.toMap( SSOUserInfoRespDto::getId, Function.identity() ));

			vos.forEach( e -> {
				SSOUserInfoRespDto createUserInfo = userInfoRespDtoMap.get(e.getCreateUserId());
				SSOUserInfoRespDto updateUserInfo = userInfoRespDtoMap.get(e.getUpdateUserId());
				e.setCreateUserName(createUserInfo == null ? "" : createUserInfo.getName());
				e.setUpdateUserName(updateUserInfo == null ? "" : updateUserInfo.getName());
			});
		}
		return vos;
	}

	public SSORespBody postSSO(String reqUrl, String reqBody){
		Map<String,String> header=new HashMap<>();
		header.put("App-Name",appName);

		OKHttpClientManage okHttpClientManage = OKHttpClientManage.getOkHttpClientManage(reqUrl);
		try {
			String respStr = okHttpClientManage.post(reqBody,OKHttpClientManage.MEDIATYPE_JSON,header);
			log.info("reqUrl=" + reqUrl + " ,responseBody=" + respStr);
			SSORespBody ssoRespBody = JSONObject.parseObject(respStr,SSORespBody.class);
			if("000000".equals(ssoRespBody.getCode())){
				return ssoRespBody;
			}else{
				throw new ApiException(AUTH_SSO_SYSTEM_ERROR.getCode(),AUTH_SSO_SYSTEM_ERROR.getMessage() + ",responseBody="+respStr);
			}
		} catch (Exception e) {
			throw new ApiException(AUTH_SSO_SYSTEM_ERROR.getCode(),AUTH_SSO_SYSTEM_ERROR.getMessage(),e);
		}
	}
}
